#include "opt_vector.h"
#include <fstream>

opt_vector::opt_vector()
{
	length_ = 0;
	capacity_ = 1;
};

opt_vector::~opt_vector()
{
	if (length_ > 1)
	{
		delete digits;
	}
};

opt_vector::opt_vector(long long num)
{
	length_ = 1;
	capacity_ = 1;
	digit = num;
};

opt_vector::opt_vector(int length, long long fill)
{
	length_ = length;
	if (length == 1)
	{
		capacity_ = 1;
		digit = fill;
	}
	else
	{
		capacity_ = 2 * length_;
		digits = new long long[capacity_];
		for (int i = 0; i < length_; i++)
		{
			digits[i] = fill;
		}
	}
};

bool opt_vector::empty() const
{
	return (length_ == 0);
};

int opt_vector::begin()
{
	return 0;
};

int opt_vector::end()
{
	return length_ - 1;
};

long long opt_vector::back() 
{
	if (length_ > 0)
		return digits[length_ - 1];
	return digit;
};

int opt_vector::size() const
{
	return length_;
};

int opt_vector::capacity() const
{
	return capacity_;
};

void opt_vector::push_back(long long number)
{
	if (length_ == 0)
	{
		capacity_ = 1;
		delete digits;
		digit = number;
		return;
	}
	if (length_ == 1)
	{
		length_++;
		capacity_ *= 2;
		long long tmp = digit;
		digits = new long long[capacity_];
		digits[0] = tmp;
		digits[1] = number;
		return;
	}
	if (length_ == capacity_)
	{
		capacity_ *= 2;
		long long* temp = new long long[capacity_];
		for (int i = 0; i < length_; i++)
		{
			temp[i] = digits[i];
		}
		delete digits;
		digits = temp;
	}
	digits[length_++] = number;
};

long long opt_vector::pop_back()
{
	if (length_ == 0)
	{
		throw std::runtime_error("attempt to apply to a number in empty vector");
	}
	if (length_ == 1)
	{
		capacity_ = 1;
		length_ = 0;
		return digit;
	}
	if (length_ == 2)
	{
		length_ = 1;
		capacity_ = 1;
		long long tmp1 = digits[0];
		long long tmp2 = digits[1];
		delete digits;
		digit = tmp1;
		return tmp2;
	}
	return digits[--length_];
};

opt_vector& opt_vector::operator = (const opt_vector& vect)
{
	if (length_ > 1)
	{
		delete digits;
	}
	length_ = vect.length_;
	capacity_ = vect.capacity_;
	if (length_ < 2)
	{
		digit = vect.digit;
	}
	else
	{
		digits = new long long[capacity_];
		copy(vect.digits, 0, length_);
	}
	return *this;
};

long long opt_vector::operator[] (int pos) const
{
	if (length_ == 1)
	{
		return digit;
	}
	else
	{
		return digits[pos];
	}
};

long long& opt_vector::operator[] (int pos)
{
	if (length_ == 1)
	{
		return digit;
	}
	else
	{
		return digits[pos];
	}
};

void opt_vector::copy(const long long* sourse, const int& iter_first, const int& length)
{
	for (int i = 0; i < length; i++)
	{
		digits[i + iter_first] = sourse[i];
	}
};

void opt_vector::insert(const int& first, const int& length, const long long fill)
{
	if (first + length > capacity_)
	{
		capacity_ = 2 * (first + length);
		long long* temp = new long long[capacity_];
		for (int i = 0; i < length_; i++)
		{
			temp[i] = digits[i];
		}
		delete digits;
		digits = temp;
	}
	for (int i = first; i < first + length; i++)
	{
		digits[i] = fill;
	}
};

void opt_vector::resize(const int& new_size)
{
	if (new_size == 0)
	{
		if (capacity_ > 1)
			delete digits;
		digit = 0;
		length_ = 0;
		capacity_ = 1;
		return;
	}
	if (new_size == 1)
	{
		long long tmp = digits[0];
		if (capacity_ > 1)
			delete digits;
		digit = tmp;
		capacity_ = length_ = 1;
		return;
	}
	long long* tmp = new long long[new_size];
	for (int i = 0; i < std::min(new_size, length_); i++)
	{
		tmp[i] = digits[i];
	}
	if (capacity_ > 1)
		delete digits;
	tmp = digits;
	length_ = capacity_ = new_size;
};

void opt_vector::reverse()
{
	if (length_ == 1)
	{
		return;
	}
	for (int i = 0; i < length_ / 2; i++)
	{
		std::swap(digits[i], digits[length_ - i - 1]);
	}
};